﻿using Abp.Authorization;
using Abp.UI;
using Paas.App.Interface.Approvals;
using Paas.App.Interface.Approvals.Dtos;
using Paas.App.Interface.Approvals.Messages;
using Paas.Core;
using Paas.Core.Approvals.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Basefr.App;
using Basefr.Core.Consts.Enums;
using Basefr.Core.Extensions;
using System.Collections.Generic;
using System.Linq;

namespace Paas.App.Approvals
{
    [Route("Approve-Template")]
    [AbpAuthorize()]
    public class ApproveTemplateAppService : AppService, IApproveTemplateAppService
    {
        private readonly IMainRepository<ApproveTemplate> _templateRepo;
        private readonly IMainRepository<ApproveTemplateStep> _templateStepRepo;
        private readonly IMainRepository<ApproveTemplateStepOperator> _templateStepOperatorRepo;
        private readonly IMainRepository<Approve> _approveRepo;

        public ApproveTemplateAppService(IMainRepository<ApproveTemplate> templateRepo, IMainRepository<Approve> approveRepo, IMainRepository<ApproveTemplateStep> templateStepRepo, IMainRepository<ApproveTemplateStepOperator> templateStepOperatorRepo)
        {
            _templateRepo = templateRepo;
            _approveRepo = approveRepo;
            _templateStepRepo = templateStepRepo;
            _templateStepOperatorRepo = templateStepOperatorRepo;
        }

        [HttpPost(nameof(SearchApproveTemplate))]
        public virtual SearchApproveTemplateOutput SearchApproveTemplate(SearchApproveTemplateInput input)
        {
            var result = _templateRepo.GetAll().Include(p => p.Steps).ThenInclude(p => p.Operators).ThenInclude(p => p.Operator).OrderBy(p => p.Type).ToList();
            return new SearchApproveTemplateOutput { Items = ObjectMapper.Map<List<ApproveTemplateDto>>(result) };
        }

        [HttpPost(nameof(SaveApproveTemplate))]
        public virtual SaveApproveTemplateOutput SaveApproveTemplate(SaveApproveTemplateInput input)
        {
            if (input.Item.Steps == null || !input.Item.Steps.Any())
            {
                throw new UserFriendlyException("审批流程至少应包含两个节点");
            }

            if (input.Item.Steps.Any(s => string.IsNullOrWhiteSpace(s.Name)))
            {
                throw new UserFriendlyException("请填写流程节点名称");
            }

            var template = _templateRepo.GetAll().Include(p => p.Steps).ThenInclude(p => p.Operators).ThenInclude(p => p.Operator).First(input.Item.Id);

            var existApprove = _approveRepo.GetAll().FirstOrDefault(p => p.TemplateId == template.Id && (p.State == EnumApproveState.Pending || p.State == EnumApproveState.OnGoing));
            if (existApprove != null)
            {
                throw new UserFriendlyException("当前审批流程存在尚未完成的审批记录，不能修改该流程配置");
            }

            template.Steps.ForEach(s =>
            {
                _templateStepOperatorRepo.Delete(s.Operators);
                _templateStepRepo.Delete(s);
            });

            ApproveTemplateStep previous = null;
            var index = 0;
            input.Item.Steps.ForEach(s =>
            {
                var newStep = new ApproveTemplateStep
                {
                    Template = template,
                    Name = s.Name,
                    SortIndex = index++,
                    OperateByInitiator = s.OperateByInitiator,
                    ChangeObjectState = s.ChangeObjectState
                };

                _templateStepRepo.InsertAndGetId(newStep);

                s.Operators?.ForEach(r =>
                {
                    _templateStepOperatorRepo.Insert(new ApproveTemplateStepOperator
                    {
                        TemplateStep = newStep,
                        OperatorId = r.OperatorId
                    });
                });

                if (previous != null)
                {
                    previous.Next = newStep;
                }

                previous = newStep;
            });

            return new SaveApproveTemplateOutput { Item = ObjectMapper.Map<ApproveTemplateDto>(template) };
        }
    }
}

